package logging

import (
	"fmt"
	"sort"
	"strconv"
	"strings"
	"sync"

	"SinaNyaLite/controller"
	. "SinaNyaLite/db"
	"SinaNyaLite/tools"
	. "SinaNyaLite/tools"
	"github.com/Mrs4s/MiraiGo/client"
	"github.com/Mrs4s/MiraiGo/message"
)

func init() {
	instance = &logging{}
	controller.RegisterModule(instance)
}

type logging struct {
}

func (m *logging) MiraiGoModule() controller.ModuleInfo {
	return controller.ModuleInfo{
		ID:       "internal.roll",
		Instance: instance,
	}
}

func (m *logging) Init() {
	// 初始化过程
	// 在此处可以进行 Module 的初始化配置
	// 如配置读取
}

func (m *logging) PostInit() {
	// 第二次初始化
	// 再次过程中可以进行跨Module的动作
	// 如通用数据库等等
	CreateDndDb()
	CreateNameDb()
	CreatePasswordDb()
}

func (m *logging) Serve(b *controller.Bot) {
	// 注册服务函数部分
	registerLog(b)
}

func (m *logging) Start(b *controller.Bot) {
	// 此函数会新开携程进行调用
	// ```go
	// 		go exampleModule.Start()
	// ```

	// 可以利用此部分进行后台操作
	// 如http服务器等等
}

func (m *logging) Stop(b *controller.Bot, wg *sync.WaitGroup) {
	// 别忘了解锁
	defer wg.Done()
	// 结束部分
	// 一般调用此函数时，程序接收到 os.Interrupt 信号
	// 即将退出
	// 在此处应该释放相应的资源或者对状态进行保存
}

var instance *logging

var logger = tools.GetModuleLogger("internal.logging")

func logGroupMessage(msg *message.GroupMessage) {
	logger.
		WithField("from", "GroupMessage").
		WithField("MessageID", msg.Id).
		WithField("MessageIID", msg.InternalId).
		WithField("GroupCode", msg.GroupCode).
		WithField("SenderID", msg.Sender.Uin).
		Info(msg.ToString())
}

func logPrivateMessage(msg *message.PrivateMessage) {
	logger.
		WithField("from", "PrivateMessage").
		WithField("MessageID", msg.Id).
		WithField("MessageIID", msg.InternalId).
		WithField("SenderID", msg.Sender.Uin).
		WithField("Target", msg.Target).
		Info(msg.ToString())
}

func logFriendMessageRecallEvent(event *client.FriendMessageRecalledEvent) {
	logger.
		WithField("from", "FriendsMessageRecall").
		WithField("MessageID", event.MessageId).
		WithField("SenderID", event.FriendUin).
		Info("friend message recall")
}

func logGroupMessageRecallEvent(event *client.GroupMessageRecalledEvent) {
	logger.
		WithField("from", "GroupMessageRecall").
		WithField("MessageID", event.MessageId).
		WithField("GroupCode", event.GroupCode).
		WithField("SenderID", event.AuthorUin).
		WithField("OperatorID", event.OperatorUin).
		Info("group message recall")
}

func logGroupMuteEvent(event *client.GroupMuteEvent) {
	logger.
		WithField("from", "GroupMute").
		WithField("GroupCode", event.GroupCode).
		WithField("OperatorID", event.OperatorUin).
		WithField("TargetID", event.TargetUin).
		WithField("MuteTime", event.Time).
		Info("group mute")
}

func logDisconnect(event *client.ClientDisconnectedEvent) {
	logger.
		WithField("from", "Disconnected").
		WithField("reason", event.Message).
		Warn("bot disconnected")
}

func registerLog(b *controller.Bot) {
	b.OnGroupMessageRecalled(func(qqClient *client.QQClient, event *client.GroupMessageRecalledEvent) {
		logGroupMessageRecallEvent(event)
	})

	b.OnGroupMessage(func(qqClient *client.QQClient, groupMessage *message.GroupMessage) {
		inputMessage := strings.ToLower(strings.ReplaceAll(strings.TrimSpace(groupMessage.ToString()), "。", "."))
		switch {
		case strings.HasPrefix(inputMessage, ".bot"):
			outputMessage := message.NewSendingMessage()
			outputMessage.Append(message.NewText("本机为SinaNya精简版核心，无开关功能，可以直接移出群不会记录黑名单\n仅支持以下命令\n.bot\n.r\n.rc\n.rh\n.sc\n.ri\n.init\n.init clr\n.nn"))
			qqClient.SendGroupMessage(groupMessage.GroupCode, outputMessage)
		case strings.HasPrefix(inputMessage, ".rc"):
			b, err := strconv.Atoi(strings.TrimSpace(inputMessage[3:]))
			notifyMessage := message.NewSendingMessage()
			notifyMessage.Append(message.NewText("输入的不是数字"))
			if err != nil {
				qqClient.SendGroupMessage(groupMessage.GroupCode, notifyMessage)
			}
			outputMessage := message.NewSendingMessage()
			outputMessage.Append(message.NewText(fmt.Sprintf("[%s]", SelectNameDbByGroup(groupMessage))))
			result := RollCheck(b, outputMessage)
			qqClient.SendGroupMessage(groupMessage.GroupCode, result)
		case strings.HasPrefix(inputMessage, ".sc"):
			outputMessage := message.NewSendingMessage()
			outputMessage.Append(message.NewText(fmt.Sprintf("[%s]掷出了:\t", SelectNameDbByGroup(groupMessage))))
			outputMessage = SanCheck(strings.TrimSpace(inputMessage[3:]), outputMessage)
			qqClient.SendGroupMessage(groupMessage.GroupCode, outputMessage)
		case strings.HasPrefix(inputMessage, ".rh"):
			function, result := Roll(strings.TrimSpace(inputMessage[3:]))
			outputMessage := message.NewSendingMessage()
			outputMessage.Append(message.NewText(fmt.Sprintf("%s=%d", function, result)))
			notifyMessage := message.NewSendingMessage()
			notifyMessage.Append(message.NewText(fmt.Sprintf("已私聊至[%s]", SelectNameDbByGroup(groupMessage))))
			qqClient.SendGroupMessage(groupMessage.GroupCode, notifyMessage)
			qqClient.SendPrivateMessage(groupMessage.Sender.Uin, outputMessage)
		case strings.HasPrefix(inputMessage, ".ri"):
			name := SelectNameDbByGroup(groupMessage)
			function, result := Ri(strings.TrimSpace(inputMessage[3:]), &name)
			outputMessage := message.NewSendingMessage()
			outputMessage.Append(message.NewText(fmt.Sprintf("[%s]的先攻值为%s=%d", name, function, result)))
			m := map[string]int64{
				name: int64(result),
			}
			UpsertDndDb(groupMessage.GroupCode, m)
			qqClient.SendGroupMessage(groupMessage.GroupCode, outputMessage)
		case strings.HasPrefix(inputMessage, ".init clr"):
			DeleteDndDb(groupMessage.GroupCode)
			outputMessage := message.NewSendingMessage()
			outputMessage.Append(message.NewText("已清空本群先攻列表"))
			qqClient.SendGroupMessage(groupMessage.GroupCode, outputMessage)
		case strings.HasPrefix(inputMessage, ".init"):
			dndInitMap := SelectDndDb(groupMessage.GroupCode)
			rs := NewMapSorter(dndInitMap)
			sort.Sort(rs)
			outputMessage := message.NewSendingMessage()
			outputMessage.Append(message.NewText("本群先攻值为"))
			for k, v := range rs {
				outputMessage.Append(message.NewText(fmt.Sprintf("\n%d.\t%s  \t%d", k+1, v.Key, v.Val)))
			}
			qqClient.SendGroupMessage(groupMessage.GroupCode, outputMessage)
		case strings.HasPrefix(inputMessage, ".r"):
			function, result := Roll(strings.TrimSpace(inputMessage[2:]))
			outputMessage := message.NewSendingMessage()
			outputMessage.Append(message.NewText(fmt.Sprintf("[%s]掷出了:\t", SelectNameDbByGroup(groupMessage))))
			outputMessage.Append(message.NewText(fmt.Sprintf("%s=%d", function, result)))
			qqClient.SendGroupMessage(groupMessage.GroupCode, outputMessage)
		case strings.HasPrefix(inputMessage, ".nn"):
			name := strings.TrimSpace(inputMessage[3:])
			if name != "" {
				UpsertNameDb(groupMessage.Sender.Uin, name)
				outputMessage := message.NewSendingMessage()
				outputMessage.Append(message.NewText(fmt.Sprintf("已将[%s]的名称改为[%s]", groupMessage.Sender.DisplayName(), SelectNameDbByGroup(groupMessage))))
				qqClient.SendGroupMessage(groupMessage.GroupCode, outputMessage)
			} else {
				DeleteNameDb(groupMessage.Sender.Uin)
				outputMessage := message.NewSendingMessage()
				outputMessage.Append(message.NewText(fmt.Sprintf("已将[%s]的名称复原", groupMessage.Sender.DisplayName())))
				qqClient.SendGroupMessage(groupMessage.GroupCode, outputMessage)
			}
		}
		logger.Info("已发出信息")
	})

	b.OnGroupMuted(func(qqClient *client.QQClient, event *client.GroupMuteEvent) {
		logGroupMuteEvent(event)
	})

	b.OnPrivateMessage(func(qqClient *client.QQClient, privateMessage *message.PrivateMessage) {
		inputMessage := strings.ToLower(strings.ReplaceAll(strings.TrimSpace(privateMessage.ToString()), "。", "."))
		switch {
		case strings.HasPrefix(inputMessage, ".bot"):
			outputMessage := message.NewSendingMessage()
			outputMessage.Append(message.NewText("本机为SinaNya精简版核心，无开关功能，可以直接移出群不会记录黑名单\n仅支持以下命令\n.bot\n.r\n.rc\n.rh\n.sc\n.ri\n.init\n.init clr\n.nn"))
			qqClient.SendPrivateMessage(privateMessage.Self, outputMessage)
		case strings.HasPrefix(inputMessage, ".rc"):
			b, err := strconv.Atoi(strings.TrimSpace(inputMessage[3:]))
			notifyMessage := message.NewSendingMessage()
			notifyMessage.Append(message.NewText("输入的不是数字"))
			if err != nil {
				qqClient.SendPrivateMessage(privateMessage.Self, notifyMessage)
			}
			outputMessage := message.NewSendingMessage()
			outputMessage.Append(message.NewText(fmt.Sprintf("[%s]", SelectNameDbByPrivate(privateMessage))))
			result := RollCheck(b, outputMessage)
			qqClient.SendPrivateMessage(privateMessage.Self, result)
		case strings.HasPrefix(inputMessage, ".r"):
			function, result := Roll(strings.TrimSpace(inputMessage[2:]))
			outputMessage := message.NewSendingMessage()
			outputMessage.Append(message.NewText(fmt.Sprintf("[%s]掷出了:\t", SelectNameDbByPrivate(privateMessage))))
			outputMessage.Append(message.NewText(fmt.Sprintf("%s=%d", function, result)))
			qqClient.SendPrivateMessage(privateMessage.Self, outputMessage)
		case strings.HasPrefix(inputMessage, ".sc"):
			outputMessage := message.NewSendingMessage()
			outputMessage.Append(message.NewText(fmt.Sprintf("[%s]掷出了:\t", SelectNameDbByPrivate(privateMessage))))
			outputMessage = SanCheck(strings.TrimSpace(inputMessage[3:]), outputMessage)
			qqClient.SendPrivateMessage(privateMessage.Self, outputMessage)
		case strings.HasPrefix(inputMessage, ".nn"):
			name := strings.TrimSpace(inputMessage[3:])
			if name != "" {
				UpsertNameDb(privateMessage.Sender.Uin, name)
				outputMessage := message.NewSendingMessage()
				outputMessage.Append(message.NewText(fmt.Sprintf("已将[%s]的名称改为[%s]", privateMessage.Sender.DisplayName(), SelectNameDbByPrivate(privateMessage))))
				qqClient.SendPrivateMessage(privateMessage.Self, outputMessage)
			} else {
				DeleteNameDb(privateMessage.Sender.Uin)
				outputMessage := message.NewSendingMessage()
				outputMessage.Append(message.NewText(fmt.Sprintf("已将[%s]的名称复原", privateMessage.Sender.DisplayName())))
				qqClient.SendPrivateMessage(privateMessage.Self, outputMessage)
			}
		}
		logger.Info("已发出信息")
	})

	b.OnFriendMessageRecalled(func(qqClient *client.QQClient, event *client.FriendMessageRecalledEvent) {
		logFriendMessageRecallEvent(event)
	})

	b.OnDisconnected(func(qqClient *client.QQClient, event *client.ClientDisconnectedEvent) {
		logDisconnect(event)
	})
}
